include(${CMAKE_CURRENT_LIST_DIR}/clrfeatures.cmake)

if(FEATURE_JIT)
  add_compile_definitions(FEATURE_JIT)
endif(FEATURE_JIT)

add_compile_definitions($<$<BOOL:$<TARGET_PROPERTY:DAC_COMPONENT>>:DACCESS_COMPILE>)

if (CLR_CMAKE_TARGET_UNIX)

  if (CLR_CMAKE_TARGET_ARCH_AMD64)
    add_compile_definitions($<$<NOT:$<BOOL:$<TARGET_PROPERTY:IGNORE_DEFAULT_TARGET_ARCH>>>:UNIX_AMD64_ABI>)
  elseif (CLR_CMAKE_TARGET_ARCH_ARM64)
    add_compile_definitions(FEATURE_EMULATE_SINGLESTEP)
  elseif (CLR_CMAKE_TARGET_ARCH_ARM)
    add_compile_definitions($<$<NOT:$<BOOL:$<TARGET_PROPERTY:IGNORE_DEFAULT_TARGET_ARCH>>>:UNIX_ARM_ABI>)
    add_compile_definitions(FEATURE_EMULATE_SINGLESTEP)
  elseif (CLR_CMAKE_TARGET_ARCH_I386)
    add_compile_definitions($<$<NOT:$<BOOL:$<TARGET_PROPERTY:IGNORE_DEFAULT_TARGET_ARCH>>>:UNIX_X86_ABI>)
  elseif (CLR_CMAKE_TARGET_ARCH_LOONGARCH64)
    add_compile_definitions(FEATURE_EMULATE_SINGLESTEP)
  elseif (CLR_CMAKE_TARGET_ARCH_RISCV64)
    add_compile_definitions(FEATURE_EMULATE_SINGLESTEP)
  endif()

endif(CLR_CMAKE_TARGET_UNIX)

if (CLR_CMAKE_TARGET_APPLE AND CLR_CMAKE_TARGET_ARCH_ARM64)
  add_compile_definitions($<$<NOT:$<BOOL:$<TARGET_PROPERTY:IGNORE_DEFAULT_TARGET_ARCH>>>:OSX_ARM64_ABI>)
endif(CLR_CMAKE_TARGET_APPLE AND CLR_CMAKE_TARGET_ARCH_ARM64)

if(CLR_CMAKE_TARGET_LINUX_MUSL)
  # musl-libc doesn't have fixed stack limit, this define disables some stack pointer
  # sanity checks in debug / checked build that rely on a fixed stack limit
  add_definitions(-DNO_FIXED_STACK_LIMIT)
endif(CLR_CMAKE_TARGET_LINUX_MUSL)

add_definitions(-DDEBUGGING_SUPPORTED)
add_compile_definitions($<$<NOT:$<BOOL:$<TARGET_PROPERTY:DAC_COMPONENT>>>:PROFILING_SUPPORTED>)
add_compile_definitions($<$<BOOL:$<TARGET_PROPERTY:DAC_COMPONENT>>:PROFILING_SUPPORTED_DATA>)

if(CLR_CMAKE_HOST_WIN32)
  add_definitions(-DWIN32)
  add_definitions(-D_WIN32)
  add_definitions(-DWINVER=0x0602)
  add_definitions(-D_WIN32_WINNT=0x0602)
  add_definitions(-DWIN32_LEAN_AND_MEAN)
  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
  add_compile_definitions(NOMINMAX)
endif(CLR_CMAKE_HOST_WIN32)

if (NOT ((CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX) OR CLR_CMAKE_TARGET_ARCH_WASM))
  add_compile_definitions(FEATURE_METADATA_UPDATER)
endif()
if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_WIN32))
  add_compile_definitions(FEATURE_REMAP_FUNCTION)
endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_WIN32))

if(CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_TARGET_ARCH_AMD64)
add_compile_definitions(OUT_OF_PROCESS_SETTHREADCONTEXT)
endif(CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_TARGET_ARCH_AMD64)

add_definitions(-DFEATURE_COLLECTIBLE_TYPES)

if(CLR_CMAKE_TARGET_WIN32)
    add_definitions(-DFEATURE_COMINTEROP)
    add_definitions(-DFEATURE_COMINTEROP_APARTMENT_SUPPORT)
    add_definitions(-DFEATURE_COMINTEROP_UNMANAGED_ACTIVATION)
    add_definitions(-DFEATURE_IJW) # C++/CLI managed/native interop support
endif(CLR_CMAKE_TARGET_WIN32)

add_definitions(-DFEATURE_BASICFREEZE)
add_definitions(-DFEATURE_CORECLR)
if(FEATURE_DBGIPC)
  add_definitions(-DFEATURE_DBGIPC_TRANSPORT_DI)
  add_definitions(-DFEATURE_DBGIPC_TRANSPORT_VM)
endif(FEATURE_DBGIPC)
add_definitions(-DFEATURE_DEFAULT_INTERFACES)
if(FEATURE_AUTO_TRACE)
    add_compile_definitions(FEATURE_AUTO_TRACE)
endif(FEATURE_AUTO_TRACE)
if(FEATURE_EVENT_TRACE)
    add_compile_definitions(FEATURE_EVENT_TRACE)
    add_definitions(-DFEATURE_PERFTRACING)
else(FEATURE_EVENT_TRACE)
    add_custom_target(eventing_headers) # add a dummy target to avoid checking for FEATURE_EVENT_TRACE in multiple places
endif(FEATURE_EVENT_TRACE)
if(FEATURE_GDBJIT)
    add_definitions(-DFEATURE_GDBJIT)
endif()
if(FEATURE_GDBJIT_FRAME)
    add_definitions(-DFEATURE_GDBJIT_FRAME)
endif(FEATURE_GDBJIT_FRAME)
if(FEATURE_GDBJIT_LANGID_CS)
    add_definitions(-DFEATURE_GDBJIT_LANGID_CS)
endif(FEATURE_GDBJIT_LANGID_CS)
if(FEATURE_GDBJIT_SYMTAB)
    add_definitions(-DFEATURE_GDBJIT_SYMTAB)
endif(FEATURE_GDBJIT_SYMTAB)
if(FEATURE_EVENTSOURCE_XPLAT)
    add_definitions(-DFEATURE_EVENTSOURCE_XPLAT)
endif(FEATURE_EVENTSOURCE_XPLAT)
# NetBSD doesn't implement this feature
if(NOT CLR_CMAKE_TARGET_NETBSD AND NOT CLR_CMAKE_TARGET_ARCH_WASM)
    add_definitions(-DFEATURE_HIJACK)
endif(NOT CLR_CMAKE_TARGET_NETBSD AND NOT CLR_CMAKE_TARGET_ARCH_WASM)
if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64))
    add_definitions(-DFEATURE_INTEROP_DEBUGGING)
endif (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64))

add_compile_definitions($<${FEATURE_INTERPRETER}:FEATURE_INTERPRETER>)
if (FEATURE_PORTABLE_ENTRYPOINTS)
  add_compile_definitions(FEATURE_PORTABLE_ENTRYPOINTS)
endif()
if (FEATURE_PORTABLE_HELPERS)
  add_compile_definitions(FEATURE_PORTABLE_HELPERS)
endif()

if (CLR_CMAKE_TARGET_WIN32)
    add_definitions(-DFEATURE_ISYM_READER)
endif(CLR_CMAKE_TARGET_WIN32)

if(FEATURE_STATICALLY_LINKED)
  add_compile_definitions($<$<NOT:$<BOOL:$<TARGET_PROPERTY:IGNORE_FEATURE_STATICALLY_LINKED>>>:FEATURE_STATICALLY_LINKED>)
endif(FEATURE_STATICALLY_LINKED)
add_compile_definitions(FEATURE_MULTICOREJIT)
if(CLR_CMAKE_TARGET_UNIX)
  add_definitions(-DFEATURE_PAL_ANSI)
endif(CLR_CMAKE_TARGET_UNIX)
if(CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_HOST_LINUX)
    add_definitions(-DFEATURE_PERFMAP)
endif(CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_HOST_LINUX)
if(CLR_CMAKE_TARGET_FREEBSD)
    add_compile_definitions(FEATURE_PERFMAP)
endif(CLR_CMAKE_TARGET_FREEBSD)
if(CLR_CMAKE_TARGET_APPLE)
    add_compile_definitions(FEATURE_PERFMAP)
endif(CLR_CMAKE_TARGET_APPLE)

if(FEATURE_COMWRAPPERS)
    add_compile_definitions(FEATURE_COMWRAPPERS)
endif(FEATURE_COMWRAPPERS)

if(FEATURE_TYPEEQUIVALENCE)
    add_compile_definitions(FEATURE_TYPEEQUIVALENCE)
endif(FEATURE_TYPEEQUIVALENCE)

if(FEATURE_OBJCMARSHAL)
  add_compile_definitions(FEATURE_OBJCMARSHAL)
endif()

add_compile_definitions($<${FEATURE_JAVAMARSHAL}:FEATURE_JAVAMARSHAL>)

add_compile_definitions($<$<NOT:$<BOOL:$<TARGET_PROPERTY:DAC_COMPONENT>>>:FEATURE_PROFAPI_ATTACH_DETACH>)

add_definitions(-DFEATURE_READYTORUN)

set(FEATURE_READYTORUN 1)

if(FEATURE_REJIT)
  add_compile_definitions(FEATURE_REJIT)
endif()

if (CLR_CMAKE_HOST_UNIX AND CLR_CMAKE_TARGET_UNIX)
  add_definitions(-DFEATURE_REMOTE_PROC_MEM)
endif (CLR_CMAKE_HOST_UNIX AND CLR_CMAKE_TARGET_UNIX)

if (FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION)
  add_definitions(-DFEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION)
endif(FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION)
if (NOT CLR_CMAKE_HOST_ANDROID)
  set(FEATURE_SVR_GC 1)
  add_definitions(-DFEATURE_SVR_GC)
endif(NOT CLR_CMAKE_HOST_ANDROID)
add_definitions(-DFEATURE_SYMDIFF)

if (FEATURE_TIERED_COMPILATION)
  add_compile_definitions(FEATURE_CODE_VERSIONING)
  add_compile_definitions(FEATURE_TIERED_COMPILATION)
endif(FEATURE_TIERED_COMPILATION)

add_compile_definitions(FEATURE_PGO)
if (CLR_CMAKE_TARGET_ARCH_AMD64)
  # Enable the AMD64 Unix struct passing JIT-EE interface for all AMD64 platforms, to enable altjit.
  add_definitions(-DUNIX_AMD64_ABI_ITF)
endif (CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-DFEATURE_USE_ASM_GC_WRITE_BARRIERS)
if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64 OR CLR_CMAKE_TARGET_ARCH_ARM)
  add_definitions(-DFEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP)
endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64 OR CLR_CMAKE_TARGET_ARCH_ARM)
if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64)
  add_definitions(-DFEATURE_MANUALLY_MANAGED_CARD_BUNDLES)
endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64)

add_definitions(-D_SECURE_SCL=0)
add_definitions(-DUNICODE)
add_definitions(-D_UNICODE)

if(CLR_CMAKE_TARGET_WIN32)
  if (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386)
    add_definitions(-DFEATURE_DATABREAKPOINT)
  endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386)
endif(CLR_CMAKE_TARGET_WIN32)

add_compile_definitions($<$<NOT:$<BOOL:$<TARGET_PROPERTY:IGNORE_DEFAULT_TARGET_ARCH>>>:FEATURE_EH_FUNCLETS>)

if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64))
  add_definitions(-DFEATURE_SPECIAL_USER_MODE_APC)
endif()

if (FEATURE_STUBPRECODE_DYNAMIC_HELPERS)
  add_definitions(-DFEATURE_STUBPRECODE_DYNAMIC_HELPERS)
endif()

if (FEATURE_CORECLR_FLUSH_INSTRUCTION_CACHE_TO_PROTECT_STUB_READS)
  add_definitions(-DFEATURE_CORECLR_FLUSH_INSTRUCTION_CACHE_TO_PROTECT_STUB_READS)
endif()

if (CLR_CMAKE_TARGET_APPLE)
 add_definitions(-DFEATURE_MAP_THUNKS_FROM_IMAGE)
endif()

# Use this function to enable building with a specific target OS and architecture set of defines
# This is known to work for the set of defines used by the JIT and gcinfo, it is not likely correct for
# other components of the runtime
function(set_target_definitions_to_custom_os_and_arch)
  set(oneValueArgs TARGET OS ARCH)
  cmake_parse_arguments(TARGETDETAILS "" "${oneValueArgs}" "" ${ARGN})

  set_target_properties(${TARGETDETAILS_TARGET} PROPERTIES IGNORE_DEFAULT_TARGET_ARCH TRUE)
  set_target_properties(${TARGETDETAILS_TARGET} PROPERTIES IGNORE_DEFAULT_TARGET_OS TRUE)

  if (TARGETDETAILS_OS STREQUAL "browser")
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_UNIX)
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_BROWSER)
  endif()
  if (TARGETDETAILS_OS STREQUAL "wasi")
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_UNIX)
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_WASI)
  endif()
  if ((TARGETDETAILS_OS MATCHES "^unix"))
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_UNIX)
    if (TARGETDETAILS_ARCH STREQUAL "x64")
      target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE UNIX_AMD64_ABI)
    elseif ((TARGETDETAILS_ARCH STREQUAL "arm") OR (TARGETDETAILS_ARCH STREQUAL "armel"))
      target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE UNIX_ARM_ABI)
    elseif (TARGETDETAILS_ARCH STREQUAL "x86")
      target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE UNIX_X86_ABI)
    elseif (TARGETDETAILS_ARCH STREQUAL "arm64")
    elseif (TARGETDETAILS_ARCH STREQUAL "loongarch64")
    endif()
    if ((TARGETDETAILS_ARCH STREQUAL "arm64") AND (TARGETDETAILS_OS STREQUAL "unix_osx"))
      target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_APPLE)
      target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE OSX_ARM64_ABI)
    endif()
    if (TARGETDETAILS_OS STREQUAL "unix_osx")
      target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_APPLE)
      target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_OSX)
    endif()
    if (TARGETDETAILS_OS STREQUAL "unix_anyos")
      target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_UNIX_ANYOS)
    endif()
  elseif (TARGETDETAILS_OS MATCHES "^win")
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_WINDOWS)
  endif((TARGETDETAILS_OS MATCHES "^unix"))

  if (TARGETDETAILS_ARCH STREQUAL "x86")
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_X86)
  elseif(TARGETDETAILS_ARCH STREQUAL "x64")
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_64BIT)
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_AMD64)
  elseif(TARGETDETAILS_ARCH STREQUAL "arm64")
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_64BIT)
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_ARM64)
  elseif(TARGETDETAILS_ARCH STREQUAL "loongarch64")
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_64BIT)
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_LOONGARCH64)
  elseif((TARGETDETAILS_ARCH STREQUAL "arm") OR (TARGETDETAILS_ARCH STREQUAL "armel"))
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_ARM)
  elseif((TARGETDETAILS_ARCH STREQUAL "riscv64"))
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_64BIT)
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_RISCV64)
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE FEATURE_MULTIREG_RETURN)
  elseif(TARGETDETAILS_ARCH STREQUAL "wasm")
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_WASM)
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_WASM32)
  endif()

  if (TARGETDETAILS_ARCH STREQUAL "armel")
    target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE ARM_SOFTFP)
  endif()
endfunction()
